package com.group.controller;


import com.base.view.GeneralResult;
import com.group.model.CoinChargeInfo;
import com.group.util.CoinRandomDecimal;
import com.group.util.CoinTransferUtil;
import com.group.util.NoteException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.Collections;
import java.util.List;

/**
 * 数字货币的币币转账
 *
 * @author Zhangyang Hu
 */
@Controller
public class CoinTransferController extends BaseController {

    private static final Logger logger = LoggerFactory.getLogger(CoinTransferController.class);

    private static int randomListIndex = 0;

    private static final Object lock = new Object();

    /**
     * 返回用户欲充值金额的真正充值金额
     *
     * @param userId
     *
     * @param cid
     *
     * @param amount
     *               用户欲充值金额，为正整数
     *
     * @return
     *
     * @throws Exception
     */
    @RequestMapping(value = "/coin/charge", method = RequestMethod.GET)
    @ResponseBody
    public GeneralResult<Double> getChargeAmount(Long userId, String cid, Integer amount) throws Exception {

        if(userId == null || amount == null || cid == null) {
            throw new NoteException("userId, amount, cid 不能为空");
        }

        if(amount < 1000) {
            throw new NoteException("充值数值必须大于等于1000");
        }

        if(CoinTransferUtil.firstRun) {
            CoinTransferUtil.firstRun = false;
            this.firstRunAction();
        }

        String wantValue = null;
        int tempIndex;
        synchronized (lock) {

            int sz = CoinTransferUtil.randomList.size();

            while(true) {

                if(randomListIndex >= sz) {
                    randomListIndex = 0;
                }

                if(CoinTransferUtil.randomList.get(randomListIndex).available) {

                    wantValue = CoinTransferUtil.randomList.get(randomListIndex).randomDecimal;
                    CoinTransferUtil.randomList.get(randomListIndex).available = false;
                    tempIndex = randomListIndex;
                    randomListIndex += 1;
                    break;
                }else {
                    randomListIndex += 1;
                }
            }
        }

        //save to db
        CoinChargeInfo info = new CoinChargeInfo();
        info.setUserId(userId);
        info.setCid(cid);
        info.setAmount(amount);
        Double doubleTmp = Double.valueOf(wantValue);
        info.setRandomPrec(doubleTmp);
        info.setTimestamp(System.currentTimeMillis());

        try {
            beanDao.save(info);
            return new GeneralResult<Double>().setValue(amount + doubleTmp);
        }catch (Exception ex) {
            CoinTransferUtil.randomList.get(tempIndex).available = true;
            logger.error("Error to insert to table CoinChargeInfo, Msg: {}", ex.getMessage());

            GeneralResult<Double> gr = new GeneralResult<>();
            gr.setSuccess(false);
            gr.setMessage(ex.getMessage());

            return gr;
        }
    }

    private void firstRunAction() {

        CoinChargeInfo info = new CoinChargeInfo();
        info.setStatus("N");

        List<CoinChargeInfo> infoList = beanDao.queryList(info);

        logger.info("First run action in controller...");

        if(infoList != null) {

            for(CoinChargeInfo rec : infoList) {

                String key = rec.getRandomPrec() + "";

                CoinRandomDecimal decTmp = new CoinRandomDecimal();
                decTmp.randomDecimal = key;
                int ind = Collections.binarySearch(CoinTransferUtil.randomList, decTmp);

                if(ind >= 0) {
                    CoinTransferUtil.randomList.get(ind).available = false;
                }
            }
        }
    }
}
